#include "esp_task_executor.h"

#include <esp_log.h>

#define TAG "TaskExecutor"

// TaskExecutor 实现
TaskExecutor::TaskExecutor(const std::string& name, uint32_t stack_size, UBaseType_t priority, BaseType_t core_id): name_(name) {
    // 创建FreeRTOS任务
    uint32_t free_heap_before = esp_get_free_heap_size();
    BaseType_t result = xTaskCreatePinnedToCore(
        [](void* arg) {
            TaskExecutor* executor = static_cast<TaskExecutor*>(arg);
            executor->ExecutorLoop();
        },
        name_.c_str(),
        stack_size,
        this,
        priority,
        &task_handle_,
        core_id
    );
    if (result != pdPASS) {
        ESP_LOGE(TAG, "创建任务执行器失败: %s", name_.c_str());
        task_handle_ = nullptr;
    } 
    else {
        uint32_t free_heap_after = esp_get_free_heap_size();
        ESP_LOGI(TAG, "任务执行器创建成功: %s, 消耗堆内存: %lu 字节 剩余堆大小: %lu", name_.c_str(), free_heap_before - free_heap_after, free_heap_after);
    }
}


TaskExecutor::~TaskExecutor() {
    ESP_LOGI(TAG, "关闭任务执行器: %s", name_.c_str());
    if (task_handle_!= nullptr) {
        vTaskDelete(task_handle_);
    }
}

void TaskExecutor::WaitForCompletion() {
    std::unique_lock<std::mutex> lock(queue_mutex_);
    
    // 使用 pending_tasks_ 作为判断依据，因为它准确反映了待处理任务数
    condition_.wait(lock, [this]() {
        bool completed = (task_queue_.empty() && pending_tasks_.load() == 0);
        return completed;
    });
}


TaskId TaskExecutor::AddTask(std::function<void()> callback, TaskType type, TaskPriority priority, const std::string& name) {
    if (!callback) {
        ESP_LOGW(TAG, "AddTask 提供空回调");
        return 0;
    }
    auto task_id = next_task_id_.fetch_add(1);
    auto task = std::make_shared<Task>(task_id, std::move(callback), type, priority, name);

    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        
        // 检查队列大小
        if (task_queue_.size() >= MAX_QUEUE_SIZE) {
            ESP_LOGW(TAG, "任务队列满 (%lu), 丢弃任务: %s", MAX_QUEUE_SIZE, name.c_str());
            return 0;
        }
        
        bool was_empty = task_queue_.empty();
        task_queue_.push(task);
        pending_tasks_++;
        
        // 只有队列之前为空或立即执行的任务才通知
        if (was_empty || type == TaskType::IMMEDIATE) {
            condition_.notify_one();
        }
    }
    return task_id;
}

TaskId TaskExecutor::AddDelayedTask(std::function<void()> callback, std::chrono::milliseconds delay, TaskPriority priority, const std::string& name) {
    if (!callback) {
        ESP_LOGW(TAG, "AddDelayedTask 提供空回调");
        return 0;
    }

    auto task_id = next_task_id_.fetch_add(1);
    auto task = std::make_shared<Task>(task_id, std::move(callback), TaskType::DELAYED, priority, name);
    task->schedule_time = std::chrono::steady_clock::now() + delay;
    
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        if (task_queue_.size() >= MAX_QUEUE_SIZE) {
            ESP_LOGW(TAG, "任务队列满 (%lu), 丢弃任务: %s", MAX_QUEUE_SIZE, name.c_str());
            return 0;
        }
        
        bool was_empty = task_queue_.empty();
        task_queue_.push(task);
        pending_tasks_++;
        
        // 只有队列之前为空时才通知
        if (was_empty) {
            condition_.notify_one();
        }
    }
    return task_id;
}

TaskId TaskExecutor::AddPeriodicTask(std::function<void()> callback, std::chrono::milliseconds interval,TaskPriority priority, const std::string& name) {
    if (!callback) {
        ESP_LOGW(TAG, "AddPeriodicTask 提供空回调");
        return 0;
    }

    auto task_id = next_task_id_.fetch_add(1);
    auto task = std::make_shared<Task>(task_id, std::move(callback), TaskType::PERIODIC, priority, name);
    task->interval = interval;
    task->schedule_time = std::chrono::steady_clock::now() + interval;
    
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        
        if (task_queue_.size() >= MAX_QUEUE_SIZE) {
            ESP_LOGW(TAG, "任务队列满 (%lu), 丢弃任务: %s", MAX_QUEUE_SIZE, name.c_str());
            return 0;
        }
        
        bool was_empty = task_queue_.empty();
        task_queue_.push(task);
        pending_tasks_++;
        
        // 只有队列之前为空时才通知
        if (was_empty) {
            condition_.notify_one();
        }
    }
    return task_id;
}

bool TaskExecutor::RemoveTask(TaskId task_id) {    
    std::lock_guard<std::mutex> lock(queue_mutex_);
    
    // 遍历队列中的任务，将匹配的任务标记为已取消
    std::priority_queue<std::shared_ptr<Task>, std::vector<std::shared_ptr<Task>>, TaskComparator> temp_queue;
    bool found = false;
    
    while (!task_queue_.empty()) {
        auto task = task_queue_.top();
        task_queue_.pop();
        
        if (task->id == task_id && task->status == TaskStatus::PENDING) {
            // 如果找到匹配的任务，并且它的状态是等待中
            // 找到目标任务，将其标记为已取消
            task->status = TaskStatus::CANCELLED;
            pending_tasks_--;
            found = true;
            ESP_LOGI(TAG, "任务已取消 - ID: %lu (%s)", task_id, task->name.c_str());
        } else {
            // 其他任务重新加入队列
            temp_queue.push(task);
        }
    }
    
    // 恢复队列
    task_queue_ = std::move(temp_queue);
    
    return found;
}

bool TaskExecutor::RemoveTask(const std::string& name) {
    if (name.empty()) {
        ESP_LOGW(TAG, "无法删除空名称的任务");
        return false;
    }
    
    std::lock_guard<std::mutex> lock(queue_mutex_);
    
    // 遍历队列中的任务，将第一个匹配名称的任务标记为已取消
    std::priority_queue<std::shared_ptr<Task>, std::vector<std::shared_ptr<Task>>, TaskComparator> temp_queue;
    bool found = false;
    
    while (!task_queue_.empty()) {
        auto task = task_queue_.top();
        task_queue_.pop();
        
        if (!found && task->name == name && task->status == TaskStatus::PENDING) {
            // 如果找到匹配的任务，并且它的状态是等待中
            // 找到第一个匹配的任务，将其标记为已取消
            task->status = TaskStatus::CANCELLED;
            pending_tasks_--;
            found = true;
            ESP_LOGI(TAG, "任务已取消 - 名称: %s (ID: %lu)", name.c_str(), task->id);
        } else {
            // 其他任务重新加入队列
            temp_queue.push(task);
        }
    }
    
    // 恢复队列
    task_queue_ = std::move(temp_queue);
    
    return found;
}

uint32_t TaskExecutor::RemoveAllTasksByName(const std::string& name) {
    if (name.empty()) {
        ESP_LOGW(TAG, "无法删除空名称的任务");
        return 0;
    }
    
    std::lock_guard<std::mutex> lock(queue_mutex_);
    
    // 遍历队列中的任务，将所有匹配名称的任务标记为已取消
    std::priority_queue<std::shared_ptr<Task>, std::vector<std::shared_ptr<Task>>, TaskComparator> temp_queue;
    uint32_t removed_count = 0;
    
    while (!task_queue_.empty()) {
        auto task = task_queue_.top();
        task_queue_.pop();
        
        if (task->name == name  && task->status == TaskStatus::PENDING) {
            // 如果找到匹配的任务，并且它的状态是等待中
            // 找到匹配的任务，将其标记为已取消
            task->status = TaskStatus::CANCELLED;
            pending_tasks_--;
            removed_count++;
        } else {
            // 其他任务重新加入队列
            temp_queue.push(task);
        }
    }
    
    // 恢复队列
    task_queue_ = std::move(temp_queue);
    
    if (removed_count > 0) {
        ESP_LOGI(TAG, "总共 %lu 个任务被取消: %s", removed_count, name.c_str());
    } else {
        ESP_LOGW(TAG, "没有找到待处理的任务: %s", name.c_str());
    }
    
    return removed_count;
}

void TaskExecutor::ExecutorLoop() {
    ESP_LOGI(TAG, "任务执行器启动: %s", name_.c_str());
    
    // 处理任务队列中的任务
    ProcessTasks();
    
    ESP_LOGI(TAG, "任务执行器循环结束: %s", name_.c_str());
    vTaskDelete(NULL); // Task deletes itself
}

void TaskExecutor::ProcessTasks() {
    while (true) {
        std::unique_lock<std::mutex> lock(queue_mutex_);
        while (task_queue_.empty())
        {
            condition_.wait(lock);
        }
        auto task = task_queue_.top();
        auto now = std::chrono::steady_clock::now();
        
        //执行任务就不需要空出CPU时间片了
        if (now >= task->schedule_time) {
            // 任务可以执行，从队列中移除
            task_queue_.pop();
            pending_tasks_--;
            
            // 释放锁来执行任务
            lock.unlock();
            ExecuteTask(task);
        }else {
            vTaskDelay(pdMS_TO_TICKS(20)); // 让出CPU时间片，避免忙等待
        }
        
    }
}

void TaskExecutor::ExecuteTask(std::shared_ptr<Task> task) {
    task->status = TaskStatus::RUNNING;
    task->callback();
    task->status = TaskStatus::COMPLETED;
    
    // 处理周期性任务:创建下次执行的任务
    if (task->type == TaskType::PERIODIC && task->status == TaskStatus::COMPLETED) {
        // ESP_LOGI(TAG, "重新添加任务: %s (ID: %lu)", task->name.c_str(), task->id);
        task->status = TaskStatus::PENDING; // 重置状态为等待中
        ReschedulePeriodicTask(task);
    }
    // 检查后续是否有任务需要处理，没有就通知线程
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        if (task_queue_.empty() && pending_tasks_ == 0) {
            condition_.notify_all();
        }
    }
}


void TaskExecutor::ReschedulePeriodicTask(std::shared_ptr<Task> task) {
    task->schedule_time = std::chrono::steady_clock::now() + task->interval;
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        
        if (task_queue_.size() >= MAX_QUEUE_SIZE) {
            ESP_LOGW(TAG, "任务队列满 (%lu), 丢弃任务: %s", MAX_QUEUE_SIZE, task->name.c_str());
            return;
        }
        
        bool was_empty = task_queue_.empty();
        task_queue_.push(task);
        pending_tasks_++;
        
        // 只有队列之前为空时才通知
        if (was_empty) {
            condition_.notify_one();
        }
    }
}
